import React, {memo, MouseEvent, useState, Dispatch, useEffect, useCallback} from 'react';
import { useParams } from "react-router-dom";
import {message} from "antd";
import { isDevelopment, assign, getStore, setStore, removeStore } from '@bastet/utils';
import { IComponentType } from '@bastet/widgets';
import type { IComponent } from '@bastet/widgets';
import { BuilderInformation, BuilderWidgetPanel, BuilderEditor, useStateReducer, Context } from '../../../builder';
import { getScene, updateScene, getWidgets } from '../../../services';
// import { loadLocalWidgets, loadRemoteWidgets } from './loadDataSource';
import { useScene, loadRemoteWidgets } from '../../../hooks';
import { widgets as testWidgetNames } from '../../../widgets.json';
import uuid from "uuid/v4";

console.log('testWidgetNames: => ', testWidgetNames)
const localWidgetObject: Map<string, Promise<any>> = (import.meta as any).glob('/src/widget/**/index.tsx');
console.log('importAsync: => ', localWidgetObject);

const localWidgetMap = await loadLocalWidgets()
const fetchWidget = (path: string) => fetch(path).then(res => res.text())

interface IWidgetRemote {
  id: string;
  version: string;
  name: string;
  type: string;
  renderProps: any;
  path: string; // "widgets/card.0.0.1.js"
  children: any[];
}

/**
 * 当前场景中用到的所有组件
 *
 * @param widgetData
 */
async function __loadRemoteWidgets(widgetData: IWidgetRemote[], debug: any) {
  const remoteWidgetMap: Map<string, any> = await loadRemoteWidgets(widgetData)
  /**
   * 当前需要调试的本地组件
   * 如果与服务器组件同名，则优先使用本地调试。
   */
  remoteWidgetMap.forEach(widget => {
    const { name } = widget.settings
    if (debug && testWidgetNames.includes(name)) {
      const localWidget = localWidgetMap.get(name)
      localWidget.settings.name = name;
      remoteWidgetMap.set(name, localWidget)
    } else {
      const remoteWidget = remoteWidgetMap.get(name)
      remoteWidgetMap.set(name, remoteWidget)
    }
  })

  console.log('remoteWidgetMap', remoteWidgetMap)
  console.log('localWidgetMap', localWidgetMap)
  // console.log('__loadRemoteWidgets', remoteWidgetMap, localWidgetMap)
  return remoteWidgetMap
}

function getInformation (state: any, path?: string) {
  if (path) {
    const pathArr = path.split('-');
    let data = null;
    while (pathArr.length) {
      const path: string = pathArr.shift() as string
      if (!data) {
        data = state[path]
      } else {
        data = data[path]
      }
    }
    console.log('getInformation => ', data, path)
    return data;
  }
}


function mergeWidget (remoteSetting: any, widgetMap: Map<string, any>) {
  return remoteSetting?.map(({ name, children, ...remoteWidget}: any = {}) => {
    const widget = widgetMap.get(name)
    const id = uuid()
    if (!widget) {
      return { name, ...remoteWidget, children: mergeWidget(children, widgetMap), id }
    } else {
      return { ...widget.settings, children: mergeWidget(children, widgetMap), id }
    }
  })
}

const useSyncCallback = (callback: any) => {
  const [proxyState, setProxyState] = useState({ current: false })

  const Func = useCallback(() => {
    setProxyState({ current: true })
  }, [proxyState])

  useEffect(() => {
    if (proxyState.current) setProxyState({ current: false })
  }, [proxyState])

  useEffect(() => {
    proxyState.current && callback()
  })

  return Func
}

// console.log(originalState)
export default memo(() => {
  const params = useParams<{id: string}>();
  const [ state, dispatch, changeField ] = useStateReducer()
  const [ scene, setScene ] = useState()
  const [ widgets, setWidgets ] = useState<Map<string, any>>(new Map)
  const [ activated, setActivePath ] = useState<string>()
  const [debugging, setDebugging ] = useState<any>(getStore('debugging'))
  // const [ information, setInformation ] = useInformationReducer<IComponent>(state as IComponent[])
  const information = getInformation(state as IComponent[], activated)
  const __onClick = (_event: MouseEvent <Element>, data: IComponent) => {
    console.log('BuilderLayout: ——————————————__onClick => ', data, information?.path)
    setActivePath(data.id)
  }

  const onUpdateScene = (scene: any, widgets: any[])=> {
    updateScene({ ...scene, widgets }).then(({code, msg}) => {
      if (code === 200) message.info(msg)
    })
  }

  useEffect(() => {
    if (!params?.id) return;
    Promise.all([getScene(params.id), getWidgets()]).then(async ([scene, widgets]: any[] = []) => {
      /**
       * 请求下来的 widget
       */
      if (widgets.code === 200 && Array.isArray(widgets.data)) {
        const remoteWidgets = await __loadRemoteWidgets(widgets.data, debugging)
        setWidgets(remoteWidgets)
        /**
         * 当前的场景
         */
        if (scene.code === 200 && scene.data) {
          const sceneWidgets = mergeWidget(scene.data.widgets, remoteWidgets)
          console.log('sceneWidgets', scene.data.widgets, sceneWidgets)
          setScene(scene.data)
          dispatch(sceneWidgets)
        }
      }
    })
  }, [params])

  useEffect(() => {
    if (params?.id) return;
    // const remoteWidgets = debugWidgets(widgets, debugging)
    // const sceneWidgets = mergeWidget(scene.data.widgets, remoteWidgets)
    // console.log('sceneWidgets', scene.data.widgets, sceneWidgets)
    // dispatch(sceneWidgets)
  }, [debugging])

  const onSave = useSyncCallback(() => {
    onUpdateScene(scene, state)
  })

  const onCancel = () => {

  }
  const onDevelop = () => {
    if (debugging) {
      removeStore('debugging')
      setDebugging('')
    } else {
      setDebugging('debug')
      setStore('debugging', 'debug')
    }
  }

  console.log(';;;;;;;;;;;;; => ', (import.meta as any).env.DEV, `debugging: => ${ debugging }`);
  // console.log('originalState: => ', state)
  console.log(`%cinit page data: => `, 'background: #8ce196;', { activated, information, scene, state, widgets});
  console.log(`%cinit page data: => `, 'background: #8ce196;', [...state.values()]);
  return (
      <div className="root-builder">
        <BuilderWidgetPanel widgets={widgets} />
        <Context.Provider value={debugging}>
          <BuilderEditor
            defaultStyle={{ width: `calc(100vw - ${!information?.path ? 100 : 420}px)` }}
            state={[...state.values()]}
            activated={activated}
            dispatch={dispatch as Dispatch<any>}
            widgets={widgets}
            onClick={__onClick}
            onSave={onSave}
            onCancel={onCancel}
            onDevelop={onDevelop}
          />
        </Context.Provider >
        {
            information?.path && (
                <BuilderInformation
                    information={information}
                    dispatch={changeField as Dispatch<any>}/>
            )
        }
      </div>
  )
})
